package com.chenailin.www.util;

import com.chenailin.www.model.vo.CaptchaVO;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;

/**
 * @author evi
 */
public class CaptchaUtil {
    private static final int WIDTH = 120;
    private static final int HEIGHT = 40;
    private static final int CODE_COUNT = 4;
    private static final int LINE_COUNT = 20;
    private static final String FONT_NAME = "微软雅黑";
    private static final int FONT_SIZE = 20;
    private static final Color[] COLOR_PALETTE = {
            new Color(0, 100, 0),
            new Color(139, 0, 0),
            new Color(0, 0, 139),
            new Color(128, 0, 128)
    };

    public static CaptchaVO generate() {
        // 生成随机字符串
        String code = generateRandomString(CODE_COUNT);

        // 创建图片
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();

        try {
            // 绘制背景和干扰元素
            drawBackground(g);
            drawInterferenceLines(g);

            // 绘制验证码
            drawCode(g, code);

            // 转为Base64
            String base64Image = convertToBase64(image);

            return new CaptchaVO(code, base64Image);
        } finally {
            g.dispose(); // 释放图形资源
        }
    }

    /**
     * 绘制背景和噪点
     */
    private static void drawBackground(Graphics2D g) {
        // 设置背景色
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        // 添加噪点
        Random random = new Random();
        for (int i = 0; i < 100; i++) {
            int x = random.nextInt(WIDTH);
            int y = random.nextInt(HEIGHT);
            g.setColor(getRandomLightColor());
            g.drawLine(x, y, x, y);
        }
    }

    /**
     * 绘制干扰线
     */
    private static void drawInterferenceLines(Graphics2D g) {
        Random random = new Random();
        for (int i = 0; i < LINE_COUNT; i++) {
            // 设置半透明干扰线
            g.setColor(new Color(
                    random.nextInt(255),
                    random.nextInt(255),
                    random.nextInt(255),
                    // 透明度
                    100));

            int x1 = random.nextInt(WIDTH / 2);
            int y1 = random.nextInt(HEIGHT);
            int x2 = random.nextInt(WIDTH / 2) + WIDTH / 2;
            int y2 = random.nextInt(HEIGHT);

            // 绘制曲线干扰线
            g.drawLine(x1, y1, x2, y2);
        }
    }

    /**
     * 绘制验证码文本
     */
    private static void drawCode(Graphics2D g, String code) {
        // 设置字体抗锯齿
        g.setRenderingHint(
                RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 绘制每个字符
        for (int i = 0; i < code.length(); i++) {
            // 设置随机颜色（从预定义调色板选择）
            g.setColor(COLOR_PALETTE[i % COLOR_PALETTE.length]);

            // 设置字体（加粗）
            Font font = new Font(FONT_NAME, Font.BOLD, FONT_SIZE);
            g.setFont(font);

            // 计算位置（添加随机偏移）
            Random random = new Random();
            int x = (WIDTH / code.length()) * i + 5;
            int y = HEIGHT / 2 + random.nextInt(HEIGHT / 3);

            // 添加旋转效果（-30到30度之间）
            double theta = Math.PI / 180 * (random.nextInt(60) - 30);
            g.rotate(theta, x, y);

            // 绘制字符
            g.drawString(String.valueOf(code.charAt(i)), x, y);

            // 恢复旋转
            g.rotate(-theta, x, y);
        }
    }

    /**
     * 生成随机字符串（排除易混淆字符）
     */
    private static String generateRandomString(int length) {
        String chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        return sb.toString();
    }

    /**
     * 生成浅色随机颜色（用于背景噪点）
     */
    private static Color getRandomLightColor() {
        Random random = new Random();
        return new Color(
                random.nextInt(55) + 200,
                random.nextInt(55) + 200,
                random.nextInt(55) + 200
        );
    }

    /**
     * 图片转Base64
     */
    private static String convertToBase64(BufferedImage image) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(image, "png", baos);
            return "data:image/png;base64," +
                    Base64.getEncoder().encodeToString(baos.toByteArray());
        } catch (IOException e) {
            throw new RuntimeException("验证码图片生成失败", e);
        }
    }
}